package me.zxk.qwert_poetry.service;

import jakarta.transaction.Transactional;
import me.zxk.qwert_poetry.dao.*;
import me.zxk.qwert_poetry.util.ApiException;
import me.zxk.qwert_poetry.dto.PoemDTO;
import me.zxk.qwert_poetry.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class PoemServiceImpl implements PoemService {
    @Autowired
    private PoemRepository poemRepository;
    @Autowired
    private AuthorRepository authorRepository;
    @Autowired
    private TagRepository tagRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private UserLikePoemRepository userLikePoemRepository;
    @Autowired
    private CollectionPoemRepository collectionPoemRepository;
    @Autowired
    private CollectionRepository collectionRepository;

    @Override
    public Poem getPoemById(int id) {
        return poemRepository.findById(id).orElse(null);
    }

    @Transactional
    @Override
    public Poem addPoem(PoemDTO poemDTO) {
        Poem poem = PoemDTO.toEntity(poemDTO);
        if (StringUtil.isNullOrEmpty(poem.getContent()))
            throw new ApiException("诗词内容不能为空", 1001);
        if (StringUtil.isNullOrEmpty(poem.getTitle()))
            throw new ApiException("诗词标题不能为空", 1002);

        Author author = authorRepository.findById(poemDTO.getAuthorId()).orElse(null);
        if (author == null)
            throw new ApiException("作者不存在", 1000);

        List<Tag> tags =
            poemDTO
            .getTagIds()
            .stream()
            .map(tagId -> tagRepository.findById(tagId).orElseThrow(() -> new ApiException("标签不存在", 1003)))
            .toList();

        poem.setTags(tags);
        poem.setAuthor(author);
        return poemRepository.save(poem);
    }

    @Override
    public Poem editPoem(PoemDTO poem) {
        Poem oldPoem = poemRepository.findById(poem.getId()).orElse(null);
        if (oldPoem == null) {
            throw new ApiException("诗词不存在", 1004);
        }
        if (poem.getContent() != null)
            oldPoem.setContent(poem.getContent());
        if (poem.getTitle() != null)
            oldPoem.setTitle(poem.getTitle());
        if (poem.getAuthorId() != null) {
            Author author = authorRepository.findById(poem.getAuthorId()).orElse(null);
            if (author == null)
                throw new ApiException("作者不存在", 1000);
            oldPoem.setAuthor(author);
        }
        if (poem.getTagIds() != null) {
            List<Tag> tags =
                poem
                .getTagIds()
                .stream()
                .map(tagId -> tagRepository.findById(tagId).orElseThrow(() -> new ApiException("标签不存在", 1003)))
                .toList();
            oldPoem.setTags(tags);
        }
        if (poem.getTranslation() != null)
            oldPoem.setTranslation(poem.getTranslation());
        if (poem.getAnnotation() != null)
            oldPoem.setAnnotation(poem.getAnnotation());
        if (poem.getAppreciation() != null)
            oldPoem.setAppreciation(poem.getAppreciation());
        return poemRepository.save(oldPoem);
    }

    @Override
    public boolean deletePoem(int id) {
        Poem poem = poemRepository.findById(id).orElse(null);
        if (poem != null) {
            poemRepository.delete(poem);
        }
        return poem != null;
    }

    @Override
    public Page<Poem> listPoems(int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        return poemRepository.findAll(pageable);
    }

    @Override
    public Page<Poem> searchPoemsByKeyword(String keyword, int page, int size) {
        return poemRepository.findAllByContentContainingOrTitleContainingOrAuthor_NameContaining(keyword, keyword, keyword, PageRequest.of(page, size));
    }

    @Override
    public Page<Poem> searchPoemsByTag(Tag tag, int page, int size) {
        return poemRepository.findAllByTags_Name(tag.getName(), PageRequest.of(page, size));
    }

    @Override
    public Page<Poem> searchPoemsByTag(int tagId, int page, int size) {
        Tag tag = tagRepository.findById(tagId).orElse(null);
        if (tag == null)
            throw new ApiException("标签不存在", 1003);
        return searchPoemsByTag(tag, page, size);
    }

    @Override
    public boolean likePoem(int poemId, int userId, boolean liked) {
        User user = userRepository.findById(userId).orElse(null);
        if (user == null)
            throw new ApiException("用户不存在", 1005);
        Poem poem = poemRepository.findById(poemId).orElse(null);
        if (poem == null)
            throw new ApiException("诗词不存在", 1004);
        if (liked && !user.getLikedPoems().contains(poem)) {
            user.getLikedPoems().add(poem);
            userRepository.save(user);
            return true;
        } else if (!liked && user.getLikedPoems().contains(poem)) {
            user.getLikedPoems().remove(poem);
            userRepository.save(user);
            return true;
        }
        return false;
    }

    @Override
    public List<Poem> listPoemsByIds(List<Integer> poemIds) {
        return poemRepository.findAllById(poemIds);
    }

    @Override
    public Integer getLikeCountById(int id) {
        return poemRepository.getLikeCountById(id);
    }

    @Override
    public Integer getCollectCountById(int id) {
        return poemRepository.getCollectCountById(id);
    }

    @Override
    public Page<Poem> listPoemsByAuthorId(int authorId, int page, int size) {
        return poemRepository.findAllByAuthor_Id(authorId, PageRequest.of(page, size));
    }

    @Override
    public Poem getRandomPoem() {
        return poemRepository.getRandomPoem();
    }

    @Override
    public Boolean isLiked(int poemId, int userId) {
        return userLikePoemRepository.findByUserIdAndPoemId(userId, poemId).isPresent();
    }

    @Override
    public Boolean isCollected(int poemId, int userId) {
        List<Collection> collections = collectionRepository.findAllByUserId(userId);
        for (Collection collection : collections) {
            if (collection.getPoems().stream().anyMatch(poem -> poem.getId() == poemId)) {
                return true;
            }
        }
        return false;
    }
}
